package com.bjsdzk.collector.one2one;

import com.aliyun.openservices.ons.api.bean.ProducerBean;
import com.bjsdzk.collector.config.MqConfig;
import com.bjsdzk.collector.constant.Constant;
import com.bjsdzk.collector.entity.MandunDataTypeEnum;
import com.bjsdzk.collector.entity.PoliceDataTypeEnum;
import com.bjsdzk.collector.entity.UpdateRealTimeData;
import com.bjsdzk.collector.entity.agreement.CallBackCmd;
import com.bjsdzk.collector.entity.agreement.SendCmd;
import com.bjsdzk.collector.entity.model.ParamsSetting;
import com.bjsdzk.collector.serviceImp.DictionariesService;
import com.bjsdzk.collector.serviceImp.ExceColleContrService;
import com.bjsdzk.collector.serviceImp.ParamsSettingService;
import com.bjsdzk.collector.utils.CRC16;
import com.bjsdzk.collector.utils.MongoUtils;
import com.bjsdzk.collector.utils.TimeUtil;
import com.bjsdzk.collector.utils.Utils;
import com.google.common.base.Joiner;
import com.google.common.primitives.Bytes;
import com.google.gson.Gson;
import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.datagram.DatagramSocket;
import io.vertx.core.datagram.DatagramSocketOptions;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.core.net.SocketAddress;
import io.vertx.ext.mongo.BulkOperation;
import io.vertx.ext.mongo.MongoClient;
import io.vertx.redis.RedisClient;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author pc
 */
public final class MandunVerticle extends BasetVerticle {
    private static Logger logger = LoggerFactory.getLogger(MandunVerticle.class);

    private AtomicInteger intc=new AtomicInteger(0);

    int dealMinInterval;

    public MandunVerticle(RedisClient redis, MongoClient mongoClient, ExceColleContrService exceColleContrService, ParamsSettingService paramsSettingService, DictionariesService dictionariesService, ProducerBean producer, MqConfig mqConfig, Environment env) {
        this.redis = redis;
        this.mongoClient = mongoClient;
        this.exceColleContrService = exceColleContrService;
        this.paramsSettingService = paramsSettingService;
        this.dictionariesService = dictionariesService;
        this.producer = producer;
        this.mqConfig = mqConfig;
        this.env = env;
        dealMinInterval=env.getProperty("md.currentData.minInterval",Integer.class)*1000*60;
    }

    @Override
    public void start() {
        getInit();
        DatagramSocket socket = vertx.createDatagramSocket(new DatagramSocketOptions()/*.setMulticastNetworkInterface("eth0")*/.setReceiveBufferSize(1024*3199).setSendBufferSize(1024*3199));
        Map<String,LinkedList<CallBackCmd>>  callBackMessage=new ConcurrentHashMap<>();
        Map<String,Queue<SendCmd>>  delayedCmd=new ConcurrentHashMap<>();
        PriorityBlockingQueue<SendCmd> sendQueue = new PriorityBlockingQueue<>();

        UdpSendCmd udpSendCmd = new UdpSendCmd(socket, sendQueue, callBackMessage,delayedCmd);
        socket.listen(port, "0.0.0.0", asyncResult -> {
            if (asyncResult.succeeded()) {
                socket.handler(packet -> {
                    SocketAddress sender = packet.sender();
                    byte[] bytes = packet.data().getBytes();
                    String datas = Utils.bytes2String(bytes);
                    logger.info("port:{},remoteAdress:{},remotePort:{},data:{}", port, sender.host(), sender.port(), datas);
                    if (!StringUtils.startsWith(datas, "F1")) {
                        logger.error("port:{},data startWith F1 check no pass", port);
                        return;
                    }
                    int totalLength = Utils.bytestoint(bytes, 4, 2) + 20;
                    if (bytes.length == totalLength) {
                        parseData(bytes, udpSendCmd,sender);
                    } else {
                        logger.error("port:{} byte data lenth not enough", port);
                        return;
                    }

                });
                startSetModel();
                startCmdConsumerMap(sendQueue,delayedCmd);
                udpStartConsumer( udpSendCmd);
                checkLine(1000 * 2, 1000 * 60 * 15, timerOtherUdp);
            } else {
                logger.debug("Listen failed:" + asyncResult.cause());
                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                asyncResult.cause().printStackTrace(new PrintStream(stream));
                String exception = stream.toString();
                logger.debug(exception);
            }
        });

    }

    public void sendCmdLocal(PriorityBlockingQueue<SendCmd> sendQueue, List<String> deviceList) {
        deviceList.forEach( device ->{
            onlyCmdLocal(sendQueue,device);
        });
    }



    protected boolean parseData(byte[] bytes,UdpSendCmd udpSendCmd,SocketAddress sender) {
        Map<String,LinkedList<CallBackCmd>>  callBackMessage = udpSendCmd.getCallBackMessage();
        DatagramSocket socket = udpSendCmd.getSocket();
        int dataLenth = bytes.length;
        if (!StringUtils.equals(CRC16.calcCrc32(Arrays.copyOfRange(bytes, 0, dataLenth - 4)), getValueBytype(bytes, dataLenth - 4, 4, String.class))) {
            logger.error("port:{},crc check no pass", port);
            return false;
        }

        String deviceId = getValueBytype(bytes, 8, 6, String.class);
        DeviceInfoUdp deviceInfoUdp = devicesInfo.get(deviceId);
        if (deviceInfoUdp == null) {
            String deviceRedisKey = getRedisKeyByDeviceId(deviceId);
            String finalDeviceId = deviceId;
            redis.exists(deviceRedisKey, h -> {
                if (h.succeeded() && h.result() > 0) {
                    redis.hgetall(deviceRedisKey, redisKeyResult -> {
                        if (redisKeyResult.succeeded()) {
                            String deviceInfo = redisKeyResult.result().toString();
                            Gson gson = new Gson();
                            DeviceInfoUdp deviceInfoUdpRedis = gson.fromJson(deviceInfo, DeviceInfoUdp.class);
                            devicesInfo.put(finalDeviceId, deviceInfoUdpRedis);
                            logger.debug(deviceInfoUdpRedis.toString());
//                            if (!deviceInfoUdpRedis.isLineStatus()) {
                            deviceInfoUdpRedis.setLineStatus(true);
                            upLineEvent(deviceInfoUdpRedis.getCompanyId(), finalDeviceId);
//                            }
                            parseData(bytes, sender, udpSendCmd, dataLenth, deviceId, deviceInfoUdpRedis);
                            if (Arrays.asList(Constant.HARDWARETYPE_58,Constant.HARDWARETYPE_59).contains(deviceInfoUdpRedis.getHardwareType())){
                                ClosesSilencFun(socket, deviceInfoUdpRedis,2000);
                                ClosesSilencFun(socket, deviceInfoUdpRedis,20000);
                                ClosesSilencFun(socket, deviceInfoUdpRedis,120*1000);
                                vertx.setTimer(25000, opertion->{
                                    uddSendCmd(socket, new SendCmd(0, deviceInfoUdpRedis.getDeviceId(), "F1B1FF000000002C5F1F96DDFFFFFF80181598F8"), -1);
                                });
                            }

                        }
                    });
                }
            });

        }else {
            parseData(bytes, sender, udpSendCmd, dataLenth, deviceId, deviceInfoUdp);
        }


        return true;
    }

    private void ClosesSilencFun(DatagramSocket socket, DeviceInfoUdp deviceInfoUdpRedis,long time) {
        vertx.setTimer(time, opertion->{
            uddSendCmd(socket, new SendCmd(0, deviceInfoUdpRedis.getDeviceId(), "F1D3E2000001000B5F165C59FFFFFF8000A3D61C7A"), -1);
        });
    }

    private void parseData(byte[] bytes, SocketAddress sender,UdpSendCmd udpSendCmd,  int dataLenth, String deviceId, DeviceInfoUdp deviceInfoUdp) {
        Map<String,LinkedList<CallBackCmd>>  callBackMessage=udpSendCmd.getCallBackMessage();
        DatagramSocket socket=udpSendCmd.getSocket();
        Map<String, Queue<SendCmd>> delayedCmd = udpSendCmd.getDelayedCmd();
        PriorityBlockingQueue<SendCmd> queue = udpSendCmd.getQueue();
        deviceInfoUdp.setLastDataTime(System.currentTimeMillis());
        deviceInfoUdp.setRemoteAddress(sender.host());
        deviceInfoUdp.setRemotePort(sender.port());
        if (!deviceInfoUdp.isLineStatus()){
            deviceInfoUdp.setLineStatus(true);
            upLineEvent(deviceInfoUdp.getCompanyId(),deviceInfoUdp.getDeviceId());
        }

        Queue<SendCmd> sendCmds = delayedCmd.get(deviceId);
        if (sendCmds!=null){
            for (int i = 0; i <sendCmds.size() ; i++) {
                queue.offer(sendCmds.poll());
            }
        }

//        devicesLastDataTime.put(deviceId, System.currentTimeMillis());
//        remoteInfoMap.put(deviceId, new DeviceInfoUdp(sender.host(), sender.port()));

        Calendar cal = Calendar.getInstance();
        TimeZone tz = TimeZone.getTimeZone("GMT");
        cal.setTimeZone(tz);

        String cmdCallkey = getValueBytype(bytes, 6, 2, String.class);

        Integer cmdId = getValueBytype(bytes, 1);
        String pre = Utils.bytes2String(Arrays.copyOfRange(bytes, 0, 3));
        String seq = Utils.bytes2String(Arrays.copyOfRange(bytes, 6, 8));

        int len = getValueBytype(bytes, 4, 2);


        CallBackCmd ele = null;
        if(cmdId==211||cmdId==181||cmdId==177||cmdId==173){
            ele = pollCallBackCmd(callBackMessage, deviceId,seq);
        }
        if (!isPolice(cmdId, 1)) {
            String str = StringUtils.join(pre, "00", "0000", seq, Long.toHexString(cal.getTimeInMillis() / 1000), "FFFFFF80");
            String crc = CRC16.calcCrc32(Utils.hexStringToByteArray(str));
            String callcmd = StringUtils.join(str, crc).toUpperCase();

            uddSendCmd(socket, new SendCmd(0, deviceId, callcmd), -1);
        }

        int pot;

        byte[] dataBytes;

        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        String currentTime = dateFormat.format(new Date());

        switch (cmdId) {
            case 164:
                //报警数据解析
                pot = 28;
                dataBytes = Arrays.copyOfRange(bytes, 16, dataLenth);
                for (int i = 0; i < len / pot; i++) {
                    JsonArray policeDate = new JsonArray();
                    JsonArray cleanPoliceDate = new JsonArray();

                    String no = getValueBytype(dataBytes, pot * i + 0, 2, String.class);
                    String code = getValueBytype(dataBytes, pot * i + 2, 1, String.class);
                    String evtId = getValueBytype(dataBytes, pot * i + 3, 1, String.class);
                    //evtId=34:总路，evtId=35：A相，evtId=36：B相，evtId=37：C相，evtId=3A：超限制报警
                    String evtLv = getValueBytype(dataBytes, pot * i + 4, 1, String.class);
                    Integer evtRe = getValueBytype(dataBytes, pot * i + 5, 1);
                    Integer evtEx = getValueBytype(dataBytes, pot * i + 6, 1);
                    String evtSp = getValueBytype(dataBytes, pot * i + 7, 4, String.class);
                    String timeStr = getValueBytype(dataBytes, pot * i + 11, 4, String.class);
                    byte[] almNBytes = Arrays.copyOfRange(dataBytes, pot * i + 15, pot * i + 19);
                    byte[] almOBytes = Arrays.copyOfRange(dataBytes, pot * i + 19, pot * i + 23);



                    if (Arrays.asList(Constant.HARDWARETYPE_51,Constant.HARDWARETYPE_52,Constant.HARDWARETYPE_53,Constant.HARDWARETYPE_54).contains(deviceInfoUdp.getHardwareType())){
                        JsonObject police=new JsonObject();
                        police.put("deviceId", StringUtils.join(deviceId,"-",evtEx));

                        Long alm_n = getValueBytype(dataBytes, pot * i + 15, 4,Long.class);
                        Long alm_o = getValueBytype(dataBytes, pot * i + 19, 4,Long.class);
                        Long alarmStatus=alm_n ^ alm_o;
                        List<BulkOperation> bulkOperationList = new ArrayList<>();


                        int switchStatus=isPolice(alm_n, BINARY_31) ? 1 : 0;

                        consumerCallBackCmds(bytes, deviceId, callBackMessage, switchStatus);
                        updateByDeviceIdAndType(new UpdateRealTimeData(deviceInfoUdp.getCompanyId(),StringUtils.join(deviceId,"-",evtEx),205,switchStatus,currentTime));

                        logger.info("alm_n:{},alm_o:{},alarmStatus:{}",Long.toBinaryString(alm_n),Long.toBinaryString(alm_o),Long.toBinaryString(alarmStatus));
                        parsePolice(policeDate, cleanPoliceDate, alm_n, police, alarmStatus,BINARY_1, PoliceDataTypeEnum.getByTypeAndItem(evtId, "shortCircuit"));
                        parsePolice(policeDate, cleanPoliceDate, alm_n, police, alarmStatus,BINARY_3, PoliceDataTypeEnum.getByTypeAndItem(evtId, "overloadAlarm"));
//                        parsePolice(policeDate, cleanPoliceDate, alm_n, police, alarmStatus,BINARY_4,PoliceDataTypeEnum.getByTypeAndItem(evtId, "temperatureWarning"));
                        parsePolice(policeDate, cleanPoliceDate, alm_n, police, alarmStatus,BINARY_5,PoliceDataTypeEnum.getByTypeAndItem(evtId, "leakageAlarm"));
                        parsePolice(policeDate, cleanPoliceDate, alm_n, police, alarmStatus,BINARY_6,PoliceDataTypeEnum.getByTypeAndItem(evtId, "OverCurrentAlarm"));
                        parsePolice(policeDate, cleanPoliceDate, alm_n, police, alarmStatus,BINARY_7,PoliceDataTypeEnum.getByTypeAndItem(evtId, "overVoltageAlarm"));
                        parsePolice(policeDate, cleanPoliceDate, alm_n, police, alarmStatus,BINARY_12,PoliceDataTypeEnum.getByTypeAndItem(evtId, "underVoltageAlarm"));
//                        parsePolice(policeDate, cleanPoliceDate, alm_n, police, alarmStatus,BINARY_13,PoliceDataTypeEnum.getByTypeAndItem(evtId, "OverVoltageWaring"));
//                        parsePolice(policeDate, cleanPoliceDate, alm_n, police, alarmStatus,BINARY_14,PoliceDataTypeEnum.getByTypeAndItem(evtId, "underVoltageWaring"));
//                        parsePolice(policeDate, cleanPoliceDate, alm_n, police, alarmStatus,BINARY_15,PoliceDataTypeEnum.getByTypeAndItem(evtId, "electricLeakageWaring"));
//                        parsePolice(policeDate, cleanPoliceDate, alm_n, police, alarmStatus,BINARY_16,PoliceDataTypeEnum.getByTypeAndItem(evtId, "currentWarning"));
                        parsePolice(policeDate, cleanPoliceDate, alm_n, police, alarmStatus,BINARY_22,PoliceDataTypeEnum.getByTypeAndItem(evtId, "temperatureAlarm"));

                    }else {
                        JsonObject police=new JsonObject();
                        police.put("deviceId", deviceId);
                        switch (evtId) {
                            case "34":
                            case "35":
                            case "36":
                            case "37":
                                int almN = Utils.toInt(almNBytes, 0);
                                int almO = Utils.toInt(almOBytes, 0);
                                String alm = Integer.toBinaryString(almN ^ almO);
                                dealPolice(alm, evtId, policeDate, deviceId);
                                break;
                            case "3A":
                                String evCode = StringUtils.leftPad(Integer.toBinaryString(evtRe), 8, "0");
                                String high = evCode.substring(0, 3);
                                String low = evCode.substring(3);
                                int highInteger = Integer.parseInt(high, 2);
                                int lowInteger = Integer.parseInt(low, 2);

                                int value = Utils.toInt(almNBytes, 0);
                                dealThresholdPolice(highInteger, lowInteger, policeDate, value, deviceId,police);

                                break;
                            case "3B":
                                evCode = StringUtils.leftPad(Integer.toBinaryString(evtRe), 8, "0");
                                high = evCode.substring(0, 3);
                                low = evCode.substring(3);
                                highInteger = Integer.parseInt(high, 2);
                                lowInteger = Integer.parseInt(low, 2);

                                value = Utils.toInt(almNBytes, 0);
                                dealThresholdPolice(highInteger, lowInteger, cleanPoliceDate, value, deviceId,police);
                                break;
                        }
                    }
                    if (!policeDate.isEmpty()) {
                        logger.debug("parse police：" + policeDate.toString());
                        eventBus.send(Constant.MOD_DEVICE_POLICE, returnResult(deviceId,policeDate));
                    }

                    if (!cleanPoliceDate.isEmpty()) {
                        logger.debug("parse clean police：" + cleanPoliceDate.toString());
                        if (Arrays.asList(Constant.HARDWARETYPE_51,Constant.HARDWARETYPE_52,Constant.HARDWARETYPE_53,Constant.HARDWARETYPE_54).contains(deviceInfoUdp.getHardwareType())){
                            eventBus.send(Constant.MOD_DEVICE_CLEANPOLICE, returnResult(deviceId,cleanPoliceDate));
                        }
                    }

                }
                break;
            case 170:
                logger.debug("port:{},deviceId:{},heartbeat",port,deviceId);
                break;
            case 172:
            case 173:
                dealCurrentData(bytes, dataLenth, deviceId, deviceInfoUdp, cmdId, len, ele,callBackMessage);
                break;
            case 176:
                deviceId=getValueBytype(bytes, 8, 6, String.class);
                String version =getValueBytype(bytes, 20, 2, String.class);
                String v= Joiner.on(".").join(version.substring(0, 1),version.substring(1, 2),Integer.parseInt(version.substring(2, 4),16) );
                updateMongoByJson(deviceInfoUdp, currentTime, v, 201);
                logger.debug("port:{},deviceId:{},nno:{},productType:{},deviceModle:{}", port, getValueBytype(bytes, 8, 6, String.class), getValueBytype(bytes, 16, String.class), getValueBytype(bytes, 17, String.class), getValueBytype(bytes, 18, 2, String.class));
                break;
            case 177:
            case 178:
                int buzzerStatus=1;
                if ((getValueBytype(bytes, 28, 2)&64)==0){
                        buzzerStatus=0;
                }
//                String imei = StringUtils.leftPad(getValueBytype(bytes, 98, 4)+"",8,"0")+StringUtils.leftPad(getValueBytype(bytes, 104, 4)+"",7,"0");
                String imsi;
                if ((getValueBytype(bytes, 108, 4)+"").startsWith("46")){
                    imsi = StringUtils.leftPad(getValueBytype(bytes, 108, 4)+"",6,"0")+StringUtils.leftPad(getValueBytype(bytes, 112, 4)+"",9,"0");
                }else {
                    byte[] imsiPre = Utils.getbytes(bytes, 104, 4);
                    byte[] imsiSuffix = Utils.getbytes(bytes, 108, 4);
                    Bytes.reverse(imsiPre);
                    Bytes.reverse(imsiSuffix);
                    imsi = StringUtils.leftPad(Utils.toInt(imsiPre,0)+"",6,"0")+StringUtils.leftPad(Utils.toInt(imsiSuffix,0)+"",9,"0");
                }
                updateMongoByJson(deviceInfoUdp, currentTime, imsi, 232);
                updateMongoByJson(deviceInfoUdp, currentTime, buzzerStatus, 233);
                rpcCallBack(bytes, ele,new JsonObject().put("status", buzzerStatus).put("imsi", imsi).put("source", deviceInfoUdp.getSource()), true, 0);
                break;
            case 180:
            case 181:
                //获取阈值
                dataBytes = Arrays.copyOfRange(bytes, 16, dataLenth);
                pot = 80;//步进长度
                JsonArray jsonArray = new JsonArray();
                for (int i = 0; i < len / pot; i++) {
                    JsonObject threshold = dealThreshold(dataBytes, pot, i,deviceInfoUdp);
                    jsonArray.add(threshold);
                }

                rpcCallBack(bytes, ele, jsonArray, true, 0);
                break;
            case 211:

                Integer valueBytype = getValueBytype(bytes, 3);
                if (valueBytype != 0) {
                    rpcCallBack(bytes, ele, null, true, 1);
                } else {
                    rpcCallBack(bytes, ele, null, true, 0);
                }

                break;
            default:
                logger.info("port:{},no parse data cmdId:{}", port, cmdId);
                break;

        }
    }

    private void consumerCallBackCmds(byte[] bytes, String deviceId, Map<String, LinkedList<CallBackCmd>> callBackMessage, int switchStatus) {
        LinkedList<CallBackCmd> callBackCmds = callBackMessage.get(deviceId);
        if(callBackCmds!=null&&callBackCmds.size()>0){
            callBackCmds.forEach(callBackCmd -> {
                if (switchStatus==0&&callBackCmd.getCmd().startsWith("F1D3A2")){
                    callBackCmds.remove(callBackCmd);
                    rpcCallBack(bytes, callBackCmd, null, true, 0);
                }else if(switchStatus==1&&callBackCmd.getCmd().startsWith("F1D3A1")){
                    callBackCmds.remove(callBackCmd);
                    rpcCallBack(bytes, callBackCmd, null, true, 0);
                }
            });

        }
    }

    private void dealCurrentData(byte[] bytes, int dataLenth, String deviceId, DeviceInfoUdp deviceInfoUdp, Integer cmdId, int len, CallBackCmd ele,Map<String,LinkedList<CallBackCmd>>  callBackMessage) {
        byte[] dataBytes;
        int pot;
        List<BulkOperation> bulkOperationList = new ArrayList<>();
        JsonArray lasteDate = new JsonArray();
        dataBytes = Arrays.copyOfRange(bytes, 20, dataLenth);

        String timeStr = getValueBytype(bytes, 16, 4, String.class);
        //步进长度
        pot = 32;
        JsonObject baseInfo = new JsonObject();
        baseInfo.put("companyId", deviceInfoUdp.getCompanyId());
        baseInfo.put("deviceId", deviceId);
        for (int i = 0; i < len / pot; i++) {
            Integer deviceAddr = getValueBytype(dataBytes, pot * i + 0, 1);
            JsonObject entity = baseInfo.copy();
            if (Arrays.asList(Constant.HARDWARETYPE_51, Constant.HARDWARETYPE_52, Constant.HARDWARETYPE_53, Constant.HARDWARETYPE_54).contains(deviceInfoUdp.getHardwareType())) {
                entity.put("deviceId", StringUtils.join(deviceId, "-", deviceAddr));
            }
            String type = getValueBytype(dataBytes, pot * i + 1, 1, String.class);
            if (StringUtils.equals("EC", type)) {
                Integer signalValue = getValueBytype(dataBytes, pot * i + 3);
                int signalCode = MandunDataTypeEnum.getByTypeAndItem(type, "signal");
                if (signalCode != 0) {
                    saveMongoJson(bulkOperationList, lasteDate, entity, signalValue, signalCode);
                }
            } else {
                //电压值
                Integer vol = getValueBytype(dataBytes, pot * i + 2, 2);
                int volCode = MandunDataTypeEnum.getByTypeAndItem(type, "vol");
                if (volCode != 0) {
                    saveMongoJson(bulkOperationList, lasteDate, entity, vol, volCode);
                }

                int lkiCode = MandunDataTypeEnum.getByTypeAndItem(type, "lki");
                if (lkiCode != 0) {
                    //漏电流值
                    Integer lki = getValueBytype(dataBytes, pot * i + 4, 2);
                    double lkiDv = new BigDecimal(lki).divide(new BigDecimal(10), 2, BigDecimal.ROUND_HALF_UP).doubleValue();
                    saveMongoJson(bulkOperationList, lasteDate, entity, lkiDv, lkiCode);
                }
                //功率值
                Integer pwr = getValueBytype(dataBytes, pot * i + 6, 4);
                double pwrDv = new BigDecimal(pwr).divide(new BigDecimal(1000)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                int pwrCode = MandunDataTypeEnum.getByTypeAndItem(type, "pwr");
                if (pwrCode != 0) {
                    saveMongoJson(bulkOperationList, lasteDate, entity, pwrDv, pwrCode);
                }
                //温度值
                Integer tmp = getValueBytype(dataBytes, pot * i + 10, 2);
                double tmpDv = new BigDecimal(tmp).divide(new BigDecimal(10), 1, BigDecimal.ROUND_HALF_UP).doubleValue();
                int tmpCode = MandunDataTypeEnum.getByTypeAndItem(type, "tmp");
                if (tmpCode != 0) {
                    saveMongoJson(bulkOperationList, lasteDate, entity, tmpDv, tmpCode);
                }
                //电流值
                Integer cur = getValueBytype(dataBytes, pot * i + 12, 4);
                double curDv = new BigDecimal(cur).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                int curCode = MandunDataTypeEnum.getByTypeAndItem(type, "cur");
                if (curCode != 0) {
                    saveMongoJson(bulkOperationList, lasteDate, entity, curDv, curCode);
                }
//第二路温度
                Integer tmp2 = getValueBytype(dataBytes, pot * i + 16, 2);
                double tmpDv2 = new BigDecimal(tmp2).divide(new BigDecimal(10), 1, BigDecimal.ROUND_HALF_UP).doubleValue();
                int tmpCode2 = MandunDataTypeEnum.getByTypeAndItem(type, "tmp2");
                if (tmpCode2 != 0) {
                    saveMongoJson(bulkOperationList, lasteDate, entity, tmpDv2, tmpCode2);
                }

//                    Integer cur2 = getValueBytype(dataBytes, pot * i + 18, 2);//电流值参考说明
                Long alarmFlag = getValueBytype(dataBytes, pot * i + 20, 4, Long.class);
                int switchType = MandunDataTypeEnum.getByTypeAndItem(type, "switchStatus");
                if (switchType != 0) {
                    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
                    String currentTime = dateFormat.format(new Date());
                    if (Arrays.asList(Constant.HARDWARETYPE_51, Constant.HARDWARETYPE_52, Constant.HARDWARETYPE_53, Constant.HARDWARETYPE_54).contains(deviceInfoUdp.getHardwareType())) {
                        updateByDeviceIdAndType(new UpdateRealTimeData(deviceInfoUdp.getCompanyId(), StringUtils.join(deviceId, "-", deviceAddr), switchType, isPolice(alarmFlag, BINARY_31) ? 1 : 0, currentTime));
                        consumerCallBackCmds(bytes, deviceId, callBackMessage,  isPolice(alarmFlag, BINARY_31) ? 1 : 0);
                    } else {
                        updateByDeviceIdAndType(new UpdateRealTimeData(deviceInfoUdp.getCompanyId(), deviceId, 205, switchType, currentTime));
                    }
                }


                int psCode = MandunDataTypeEnum.getByTypeAndItem(type, "ps");
                if (psCode != 0) {
                    //累计电量
                    Integer ps = getValueBytype(dataBytes, pot * i + 24, 8);
                    //单向有功电能
                    double psDv = new BigDecimal(ps).divide(new BigDecimal(1000), 2, BigDecimal.ROUND_HALF_UP).doubleValue();
                    //总正相有功电能
                    saveMongoJson(bulkOperationList, lasteDate, entity, psDv, psCode);
                }

            }
        }

        if (Arrays.asList(Constant.HARDWARETYPE_51,Constant.HARDWARETYPE_52,Constant.HARDWARETYPE_53,Constant.HARDWARETYPE_54).contains(deviceInfoUdp.getHardwareType())) {
            if (System.currentTimeMillis() - deviceInfoUdp.getLastCurrentDataTime() > dealMinInterval) {
                deviceInfoUdp.setLastCurrentDataTime(System.currentTimeMillis());
                saveAndSendMq(deviceId, bulkOperationList, lasteDate);
            }
        }else {
            deviceInfoUdp.setLastCurrentDataTime(System.currentTimeMillis());
            saveAndSendMq(deviceId, bulkOperationList, lasteDate);
            rpcCallBack(bytes, ele, returnResult(deviceId, lasteDate), true, 0);
        }


    }

    private void saveAndSendMq(String deviceId, List<BulkOperation> bulkOperationList, JsonArray lasteDate) {
        if (!bulkOperationList.isEmpty()) {
            saveMongoAndSend(Constant.MONGONAME_REAL, mongoClient, bulkOperationList, eventBus, lasteDate, deviceId);
            sendDataToMq(returnResult(companyId, deviceId, lasteDate, TimeUtil.getCurrentDatetime(TimeUtil.TimeFormat.LONG_DATE_PATTERN_NOT_WITH_MILSEC_NONE_Z)));
        }
    }

    private void parsePolice(JsonArray policeDate, JsonArray cleanPoliceDate, Long alm_n, JsonObject police, Long alarmStatus,int contant,int policeType) {
        if (isPolice(alarmStatus, contant)){
            if (isPolice(alm_n, contant)){
                getPolice(police, policeDate, policeType);
            }else {
                getPolice(police, cleanPoliceDate, policeType);
            }
        }
    }


    protected void updateMongoByJson(DeviceInfoUdp deviceInfoUdp, String currentTime, Object v, Integer svaeType) {
        Map<Integer, ParamsSetting>  paramsSettingAll = paramsSettingService.findAll();
        JsonObject query = new JsonObject().put("port", port).put("deviceId", deviceInfoUdp.getDeviceId()).put("type", svaeType);
        JsonObject en = query.copy();
        en.put("v", v);
        en.put("des", paramsSettingAll.get(svaeType).getDes());
        en.put("createdAt", new JsonObject().put("$date", currentTime));
        en.put("companyId", deviceInfoUdp.getCompanyId());
        MongoUtils.updateMongo(mongoClient,en,query);
    }

    protected void updateByDeviceIdAndType(UpdateRealTimeData realTimeData) {
        Map<Integer, ParamsSetting>  paramsSettingAll = paramsSettingService.findAll();
        ParamsSetting paramsSetting = paramsSettingAll.get(realTimeData.getType());
        JsonObject query = new JsonObject().put("port", port).put("deviceId", realTimeData.getDeviceId()).put("type", realTimeData.getType());
        JsonObject data = query.copy();
        data.put("value", realTimeData.getValue());
        data.put("des", paramsSetting.getDes());
        data.put("unit", paramsSetting.getUnit());
        data.put("createdAt", new JsonObject().put("$date", realTimeData.getCurrentTime()));
        data.put("companyId", realTimeData.getCompanyId());
        MongoUtils.updateMongo(mongoClient,data,query);
    }

    private void dealThresholdPolice(int highInteger, int lowInteger, JsonArray policeDate, int value, String deviceId,JsonObject police) {
        switch (lowInteger) {
            case 1:
                //短路报警
                double v4 = new BigDecimal(value).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP).doubleValue();
                switch (highInteger) {
                    case 0:
                        //单相
                        //151
                        getPolice(police, policeDate, 151, v4);
                        break;
                    case 1:
                        //A相
                        //152
                        getPolice(police, policeDate, 152, v4);
                        break;
                    case 2:
                        //B相
                        //153
                        getPolice(police, policeDate, 153, v4);
                        break;
                    case 3:
                        //C相
                        //154
                        getPolice(police, policeDate, 154, v4);
                        break;
                }
                break;
            case 3:
                double v2 = new BigDecimal(value).divide(new BigDecimal(1000), 2, BigDecimal.ROUND_HALF_UP).doubleValue();
                //过载报警
                switch (highInteger) {
                    case 0:
                        //单相
                        //306
                        getPolice(police, policeDate, 306, v2);
                        break;
                    case 1:
                        //A相
                        //286
                        getPolice(police, policeDate, 286, v2);
                        break;
                    case 2:
                        //B相
                        //287
                        getPolice(police, policeDate, 287, v2);
                        break;
                    case 3:
                        //C相
                        //288
                        getPolice(police, policeDate, 288, v2);
                        break;
                }
                break;
            case 4:
                //温度报警
                double v = new BigDecimal(value).divide(new BigDecimal(10), 2, BigDecimal.ROUND_HALF_UP).doubleValue();
                switch (highInteger) {
                    case 0:
                        //主路
                        //230
                        getPolice(police, policeDate, 230, v);
                        break;
                    case 1:
                        //A相
                        //130
                        getPolice(police, policeDate, 130, v);
                        break;
                    case 2:
                        //B相
                        //131
                        getPolice(police, policeDate, 131, v);
                        break;
                    case 3:
                        //C相
                        //132
                        getPolice(police, policeDate, 132, v);
                        break;
                }
                break;
            case 5:
                //漏电报警
                //63
                double v1 = new BigDecimal(value).divide(new BigDecimal(10), 2, BigDecimal.ROUND_HALF_UP).doubleValue();
                getPolice(police, policeDate, 63, v1);
                break;
            case 6:
                //过流报警
                double v3 = new BigDecimal(value).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP).doubleValue();
                switch (highInteger) {
                    case 0:
                        //单相
                        //228
                        getPolice(police, policeDate, 228, v3);
                        break;
                    case 1:
                        //A相
                        //156
                        getPolice(police, policeDate, 156, v3);
                        break;
                    case 2:
                        //B相
                        //157
                        getPolice(police, policeDate, 157, v3);
                        break;
                    case 3:
                        //C相
                        //158
                        getPolice(police, policeDate, 158, v3);
                        break;
                }
                break;
            case 7:
                //过压报警
                switch (highInteger) {
                    case 0:
                        //单相
                        //2291
                        getPolice(police, policeDate, 2291, value);
                        break;
                    case 1:
                        //A相
                        //91
                        getPolice(police, policeDate, 91, value);
                        break;
                    case 2:
                        //B相
                        //101
                        getPolice(police, policeDate, 101, value);
                        break;
                    case 3:
                        //C相
                        //111
                        getPolice(police, policeDate, 111, value);
                        break;
                }
                break;
            case 10:
                //打火报警
                switch (highInteger) {
                    case 0:
                        //单相
                        break;
                    case 1:
                        //A相
                        break;
                    case 2:
                        //B相
                        break;
                    case 3:
                        //C相
                        break;
                }
                break;
            case 12:
                //欠压报警
                switch (highInteger) {
                    case 0:
                        //单相
                        //2292
                        getPolice(police, policeDate, 2292, value);
                        break;
                    case 1:
                        //A相
                        //92
                        getPolice(police, policeDate, 92, value);
                        break;
                    case 2:
                        //B相
                        //102
                        getPolice(police, policeDate, 102, value);
                        break;
                    case 3:
                        //C相
                        //112
                        getPolice(police, policeDate, 112, value);
                        break;
                }
                break;
            case 13:
                //过压预警
//                switch (highInteger) {
//                    case 0:
//                        //单相
//                        //2294
//                        getPolice(police, policeDate, 2294, value);
//                        break;
//                    case 1:
//                        //A相
//                        //231
//                        getPolice(police, policeDate, 231, value);
//                        break;
//                    case 2:
//                        //B相
//                        //243
//                        getPolice(police, policeDate, 243, value);
//                        break;
//                    case 3:
//                        //C相
//                        //254
//                        getPolice(police, policeDate, 254, value);
//                        break;
//                }
//                break;
            case 14:
                //欠压预警
//                switch (highInteger) {
//                    case 0:
//                        //单相
//                        //2293
//                        getPolice(police, policeDate, 2293, value);
//                        break;
//                    case 1:
//                        //A相
//                        //233
//                        getPolice(police, policeDate, 233, value);
//                        break;
//                    case 2:
//                        //B相
//                        //245
//                        getPolice(police, policeDate, 245, value);
//                        break;
//                    case 3:
//                        //C相
//                        //256
//                        getPolice(police, policeDate, 256, value);
//                        break;
//                }
                break;
            case 15:
                //漏电预警
                //212
//                getPolice(police, policeDate, 212, value);
                break;
            case 16:
                //过流预警
//                switch (highInteger) {
//                    case 0:
//                        //单相
//                        //218
//                        getPolice(police, policeDate, 218, value);
//                        break;
//                    case 1:
//                        //A相
//                        //229
//                        getPolice(police, policeDate, 229, value);
//                        break;
//                    case 2:
//                        //B相
//                        //241
//                        getPolice(police, policeDate, 241, value);
//                        break;
//                    case 3:
//                        //C相
//                        //252
//                        getPolice(police, policeDate, 252, value);
//                        break;
//                }
                break;
            case 22:
                //温度预警
//                switch (highInteger) {
//                    case 0:
//                        //单相
//                        //216
//                        getPolice(police, policeDate, 216, value);
//                        break;
//                    case 1:
//                        //A相
//                        //235
//                        getPolice(police, policeDate, 235, value);
//                        break;
//                    case 2:
//                        //B相
//                        //423
//                        getPolice(police, policeDate, 423, value);
//                        break;
//                    case 3:
//                        //C相
//                        //258
//                        getPolice(police, policeDate, 258, value);
//                        break;
//                }
                break;
        }
    }


    @Override
    public void stop() {
        devicesInfo.forEach((k, deviceInfo) -> {
            String deviceKey = getRedisKeyByDeviceId(k);
            redis.exists(deviceKey, res -> {
                if (res.succeeded() && res.result() > 0) {
                    redis.hmset(getRedisKeyByDeviceId(k), new JsonObject().put("lastDataTime", deviceInfo.getLastDataTime()).put("lineStatus", deviceInfo.isLineStatus()), h -> {

                    });
                }
            });

        });

    }

    private JsonObject dealThreshold(byte[] dataBytes, int pot, int i, DeviceInfoUdp deviceInfoUdp) {

        Integer nno = getValueBytype(dataBytes, pot * i + 0, 1);
        String type = getValueBytype(dataBytes, pot * i + 1, 1, String.class);//产品类型：80：单项节点，85：A相，86：B相，87：C相
        Integer model = getValueBytype(dataBytes, pot * i + 2, 2);//产品型号
        Integer ver = getValueBytype(dataBytes, pot * i + 4, 2);//版本号
        Integer ser = getValueBytype(dataBytes, pot * i + 6, 4);//产品序列号
        Integer rev = getValueBytype(dataBytes, pot * i + 10, 1);//保留
        Integer cunit = getValueBytype(dataBytes, pot * i + 11, 1);//电流/功率变比倍数
        if (cunit > 0&&!cunit.equals(deviceInfoUdp.getCurrentRatio())) {
                deviceInfoUdp.setCurrentRatio(cunit);
                redis.hset(getRedisKeyByDeviceId(deviceInfoUdp.getDeviceId()), "currentRatio", cunit + "", h -> {
                    if (h.failed()) {
                        logger.error("update  currentRatio error:{}", h.cause().getMessage());
                    }
                });
        }
        byte[] ctrlBytes = Arrays.copyOfRange(dataBytes, pot * i + 12, pot * i + 14);
        String ctrl = Utils.toBinary(ctrlBytes);//控制位
        Integer volH = getValueBytype(dataBytes, pot * i + 14, 2);//电压上限
        Integer volL = getValueBytype(dataBytes, pot * i + 16, 2);//电压下限
        Integer volS = getValueBytype(dataBytes, pot * i + 18, 2);//保留
        Integer lkiH = getValueBytype(dataBytes, pot * i + 20, 2);//漏电流上限
        double lkiHDv = new BigDecimal(lkiH).divide(new BigDecimal(10), 2, BigDecimal.ROUND_HALF_UP).doubleValue();
        Integer lkiS = getValueBytype(dataBytes, pot * i + 22, 2);//保留
        Integer pwrH = getValueBytype(dataBytes, pot * i + 24, 2);//功率上限
        double pwrHDv = new BigDecimal(pwrH)
                .divide(new BigDecimal(1000)).multiply(new BigDecimal(deviceInfoUdp.getCurrentRatio())).setScale(  2, BigDecimal.ROUND_HALF_UP)
                .doubleValue();
        Integer pwrL = getValueBytype(dataBytes, pot * i + 26, 2);//功率下限
        double pwrLDv = new BigDecimal(pwrL).divide(new BigDecimal(1000)).multiply(new BigDecimal(deviceInfoUdp.getCurrentRatio())).setScale(  2, BigDecimal.ROUND_HALF_UP).doubleValue();
        Integer pwrS = getValueBytype(dataBytes, pot * i + 28, 2);//保留
        Integer tmpH = getValueBytype(dataBytes, pot * i + 30, 2);//温度上限
        double tmpHDv = new BigDecimal(tmpH).divide(new BigDecimal(10), 2, BigDecimal.ROUND_HALF_UP).doubleValue();
        Integer tmpS = getValueBytype(dataBytes, pot * i + 32, 2);//温度步长
        Integer curH = getValueBytype(dataBytes, pot * i + 34, 2);//电流上限
        double curHDv = new BigDecimal(curH)
                .divide(new BigDecimal(100)).multiply(new BigDecimal(deviceInfoUdp.getCurrentRatio())).setScale(2, BigDecimal.ROUND_HALF_UP)
                .doubleValue();
        Integer curS = getValueBytype(dataBytes, pot * i + 36, 2);//保留
        Integer rev1 = getValueBytype(dataBytes, pot * i + 38, 4);//保留
        Integer lkdT = getValueBytype(dataBytes, pot * i + 42, 4);//漏电监测时间
        Integer lkdI = getValueBytype(dataBytes, pot * i + 46, 4);//漏电监测间隔
        Integer rev2 = getValueBytype(dataBytes, pot * i + 50, 6);//保留
        String name = getValueBytype(dataBytes, pot * i + 56, 24, String.class);//线路名称

        JsonObject threshold=new JsonObject();
        threshold.put("nno", nno);
        threshold.put("type", type);
        threshold.put("model", model);
        threshold.put("ver", ver);
        threshold.put("ser", ser);
        threshold.put("rev", rev);
        threshold.put("cunit", cunit);
        threshold.put("ctrl", ctrl);
        switch (type) {
            case "E0":
                threshold.put("volH", volH);
                threshold.put("volL", volL);
                threshold.put("tmpH", tmpHDv);
                threshold.put("curH",curHDv );
                threshold.put("pwrH", pwrHDv);
                threshold.put("pwrL",pwrLDv );
                threshold.put("lkiH", lkiHDv);
                break;
            case "E4":
                threshold.put("volH", volH);
                threshold.put("volL", volL);
                threshold.put("tmpH", tmpHDv);
                threshold.put("curH",curHDv );
                threshold.put("pwrH", pwrHDv);
                threshold.put("pwrL",pwrLDv );
                threshold.put("lkiH", lkiHDv);
                break;
            case "E5":
                threshold.put("aVolH", volH);
                threshold.put("aVolL", volL);
                threshold.put("aTmpH", tmpHDv);
                threshold.put("aCurH",curHDv );
                threshold.put("aPwrH", pwrHDv);
                threshold.put("aPwrL",pwrLDv );
                break;
            case "E6":
                threshold.put("bVolH", volH);
                threshold.put("bVolL", volL);
                threshold.put("bTmpH", tmpHDv);
                threshold.put("bCurH",curHDv );
                threshold.put("bPwrH", pwrHDv);
                threshold.put("bPwrL",pwrLDv );
                break;
            case "E7":
                threshold.put("cVolH", volH);
                threshold.put("cVolL", volL);
                threshold.put("cTmpH", tmpHDv);
                threshold.put("cCurH",curHDv );
                threshold.put("cPwrH", pwrHDv);
                threshold.put("cPwrL",pwrLDv );
                break;
        }
        threshold.put("volS", volS);
        threshold.put("lkiS", lkiS);
        threshold.put("pwrS", pwrS);
        threshold.put("tmpS", tmpS);
        threshold.put("curS", curS);
        threshold.put("rev1", rev1);
        threshold.put("lkdT", StringUtils.leftPad(Integer.toBinaryString(lkdT),32,"0"));
        threshold.put("lkdI",StringUtils.leftPad(Integer.toBinaryString(lkdI),32,"0") );
        threshold.put("rev2", rev2);
        threshold.put("name",name );

        //TODO 注意实际电流（功率）上限值等于CURH(PWRH)*CUNINT
        logger.debug("start================");
        logger.debug("地址码：" + nno);
//        logger.debug("产品类型：" + type);
//        logger.debug("产品型号：" + model);
//        logger.debug("版本号：" + ver);
//        logger.debug("序列号：" + ser);
//        logger.debug("保留：" + rev);
        logger.info("电流/功率变比倍数：" + cunit);
        logger.debug("控制位：" + ctrl);
        logger.info("电压上限：" + volH);
        logger.info("电压下限：" + volL);
//        logger.debug("保留：" + volS);
        logger.info("漏电流上限：" + lkiHDv);
//        logger.debug("保留：" + lkiS);
        logger.info("功率上限：" + pwrHDv);
        logger.info("功率下限：" + pwrLDv);
//        logger.debug("保留：" + pwrS);
        logger.info("温度上限：" + tmpHDv);
//        logger.debug("温度步长：" + tmpS);
        logger.info("电流上限：" + curHDv);
//        logger.debug("保留：" + curS);
//        logger.debug("保留：" + rev1);
        logger.info("E5/E9报警使能位：" + StringUtils.leftPad(Integer.toBinaryString(lkdT),32,"0"));
        logger.info("E5脱扣使能位：" + StringUtils.leftPad(Integer.toBinaryString(lkdI),32,"0") );
//        logger.debug("保留：" + rev2);
//        logger.debug("名称：" + name);
        logger.debug("end================");

        return threshold;
    }



    private void dealPolice(String alm, String evtId, JsonArray policeDate,String deviceId) {
        alm = new StringBuffer(alm).reverse().toString();
        List<Integer> policeIndexList = new ArrayList<>();
        for (int i = -1; i <= alm.lastIndexOf("1"); ++i) {
            i = alm.indexOf("1", i);
            policeIndexList.add(i);
        }
        JsonObject police=new JsonObject();
        police.put("deviceId", deviceId);

        for (int i = 0; i < policeIndexList.size(); i++) {
            Integer policeIndex = policeIndexList.get(i);
            switch (policeIndex) {
                case 31:
                    //开关在线状态
                    break;
                case 30:
                    //开关开合状态
                    break;
                case 29:
                    //保留
                    break;
                case 28:
                    //保留
                    break;
                case 27:
                    //保留
                    break;
                case 26:
                    //保留
                    break;
                case 25:
                    //保留
                    break;
                case 24:
                    //保留
                    break;
                case 23:
                    //相序ABC
                    break;
                case 22:
                    //不平衡告警，什么不平衡，无法判断
                    break;
                case 21:
                    //保留，UDP协议1.4改为了21是温度报警，原先的3是温度预警
                    //温度报警
                    switch (evtId) {
                        case "34":
                        case "3A":
                            //230
                            getPolice(police, policeDate, 230, null);
                            break;
                        case "35":
                            //130
                            getPolice(police, policeDate, 130, null);
                            break;
                        case "36":
                            //131
                            getPolice(police, policeDate, 131, null);
                            break;
                        case "37":
                            //132
                            getPolice(police, policeDate, 132, null);
                            break;
                    }
                    break;
                case 20:
                    //保留
                    break;
                case 19:
                    //禁止相序保护
                    break;
                case 18:
                    //禁止不平衡保护
                    break;
                case 17:
                    //禁止缺相保护
                    break;
                case 16:
                    //远程合闸禁止
                    break;
                case 15:
                    //电流预警
//                    switch (evtId) {
//                        case "3A":
//                        case "34":
//                            //305
//                            getPolice(police, policeDate, 305, null);
//                            break;
//                        case "35":
//                            //229
//                            getPolice(police, policeDate, 229, null);
//                            break;
//                        case "36":
//                            //241
//                            getPolice(police, policeDate, 241, null);
//                            break;
//                        case "37":
//                            //252
//                            getPolice(police, policeDate, 252, null);
//                            break;
//                    }
                    break;
                case 14:
                    //漏电预警
                    //212
//                    getPolice(police, policeDate, 212, null);
                    break;
                case 13:
                    //欠压预警
//                    switch (evtId) {
//                        case "34":
//                        case "3A":
//                            //2293
//                            getPolice(police, policeDate, 2293, null);
//                            break;
//                        case "35":
//                            //233
//                            getPolice(police, policeDate, 233, null);
//                            break;
//                        case "36":
//                            //245
//                            getPolice(police, policeDate, 245, null);
//                            break;
//                        case "37":
//                            //256
//                            getPolice(police, policeDate, 256, null);
//                            break;
//                    }
                    break;
                case 12:
                    //过压预警
//                    switch (evtId) {
//                        case "34":
//                        case "3A":
//                            //2294
//                            getPolice(police, policeDate, 2294, null);
//                            break;
//                        case "35":
//                            //231
//                            getPolice(police, policeDate, 231, null);
//                            break;
//                        case "36":
//                            //243
//                            getPolice(police, policeDate, 243, null);
//                            break;
//                        case "37":
//                            //254
//                            getPolice(police, policeDate, 254, null);
//                            break;
//                    }
                    break;
                case 11:
                    //欠压报警
                    switch (evtId) {
                        case "34":
                        case "3A":
                            //2292
                            getPolice(police, policeDate, 2292, null);
                            break;
                        case "35":
                            //92
                            getPolice(police, policeDate, 92, null);
                            break;
                        case "36":
                            //102
                            getPolice(police, policeDate, 102, null);
                            break;
                        case "37":
                            //112
                            getPolice(police, policeDate, 112, null);
                            break;
                    }
                    break;
                case 10:
                    //打火报警
                    break;
                case 9:
                    //输入缺相（仅380）
                    switch (evtId) {
                        case "34":
                        case "3A":
                            //304
                            getPolice(police, policeDate, 304, null);
                            break;
                        case "35":
                            //236
                            getPolice(police, policeDate, 236, null);
                            break;
                        case "36":
                            //248
                            getPolice(police, policeDate, 248, null);
                            break;
                        case "37":
                            //259
                            getPolice(police, policeDate, 259, null);
                            break;
                    }
                    break;
                case 8:
                    //漏电保护自检未完成
                    break;
                case 7:
                    //漏电保护功能正常
                    break;
                case 6:
                    //过压报警
                    switch (evtId) {
                        case "34":
                        case "3A":
                            //2291
                            getPolice(police, policeDate, 2291, null);
                            break;
                        case "35":
                            //91
                            getPolice(police, policeDate, 91, null);
                            break;
                        case "36":
                            //101
                            getPolice(police, policeDate, 101, null);
                            break;
                        case "37":
                            //111
                            getPolice(police, policeDate, 111, null);
                            break;
                    }
                    break;
                case 5:
                    //过流报警
                    switch (evtId) {
                        case "34":
                        case "3A":
                            //228
                            getPolice(police, policeDate, 228, null);
                            break;
                        case "35":
                            //156
                            getPolice(police, policeDate, 156, null);
                            break;
                        case "36":
                            //157
                            getPolice(police, policeDate, 157, null);
                            break;
                        case "37":
                            //158
                            getPolice(police, policeDate, 158, null);
                            break;
                    }
                    break;
                case 4:
                    //漏电报警
                    //63
                    getPolice(police, policeDate, 63, null);
                    break;
                case 3:
                    //温度预警
                    break;
                case 2:
                    //过载报警（有功功率报警）
                    switch (evtId) {
                        case "34":
                        case "3A":
                            //306
                            getPolice(police, policeDate, 306, null);
                            break;
                        case "35":
                            //286
                            getPolice(police, policeDate, 286, null);
                            break;
                        case "36":
                            //287
                            getPolice(police, policeDate, 287, null);
                            break;
                        case "37":
                            //288
                            getPolice(police, policeDate, 288, null);
                            break;
                    }
                    break;
                case 1:
                    //浪涌报警
                    //262
                    getPolice(police, policeDate, 262, null);
                    break;
                case 0:
                    //短路报警
                    //151
                    getPolice(police, policeDate, 151, null);
                    break;
            }
        }
    }

    public byte[] getByteArray(String data) {
        byte[] bytes = data.getBytes();
        int l = bytes.length;
        byte[] result = new byte[l / 2];
        for (int i = 0, j = 0; i < l; i += 2, j++) {
            byte a = Byte.decode("0x" + new String(new byte[]{bytes[i]})).byteValue();
            byte b = Byte.decode("0x" + new String(new byte[]{bytes[i + 1]})).byteValue();
            result[j] = (byte) (((a << 4) & 0xf0) | (b & 0x0f));
        }
        return result;
    }

    class ReceiveServer implements Handler<Buffer> {

        @Override
        public void handle(Buffer buffer) {
            logger.info(buffer.toString() + port);
            logger.info(Utils.bytes2String(buffer.getBytes()) + port);
        }
    }
}

